package com.lanyou.esb.web.serviceLogManagement;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.xml.sax.SAXException;

import redis.clients.jedis.exceptions.JedisException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.gson.JsonObject;
import com.lanyou.cook.common.Constants;
import com.lanyou.cook.service.security.UserSessionService;
import com.lanyou.esb.common.CommonUtils;
import com.lanyou.esb.datadictionary.RequestResultType;
import com.lanyou.esb.datadictionary.TraceType;
import com.lanyou.esb.entity.Http;
import com.lanyou.esb.exception.ServiceHandlerException;
import com.lanyou.esb.redis.proxy.impl.HttpJedisProxy;
import com.lanyou.esb.redis.vo.HttpVo;
import com.lanyou.esb.repository.HttpRepository;
import com.lanyou.esb.service.AccessLogService;
import com.lanyou.esb.web.param.ServiceLogSearchParam;
import com.lanyou.esb.web.serviceLogManagement.vo.AccessLogVo;

/**
 * 服务日志控制器
 * 
 * @author Davey.wu
 */
@RestController
@RequestMapping(Constants.BASE_URL_API + "/serviceLogSearch")
public class ServiceLogSearchController {
	@Autowired
	AccessLogService serviceLogSearchService;

	@Autowired
	private ResourceLoader resourceLoader;

	@Autowired
	private HttpRepository httpRepository;

	@Autowired
	private HttpJedisProxy httpJedisProxy;

	@Autowired
	UserSessionService userSessionService;

	private static FastDateFormat FASTDATEFORMAT_YYYYMMDDHHMMSS = FastDateFormat
			.getInstance(Constants.DATETIME_PATTERN_1);

	/**
	 * 查找服务日志
	 * 
	 * @param param
	 * @param pageable
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/findServiceLogInfos")
	public Page<AccessLogVo> findServiceLogInfos(ServiceLogSearchParam param,
			Pageable pageable) throws Exception {

		String startDate = param.getStartDateTime();
		String endDate = param.getEndDateTime();
		if (StringUtils.isBlank(startDate)) {
			throw new Exception("开始日期不能空！");
		}
		if (StringUtils.isBlank(endDate)) {
			throw new Exception("结束日期不能空！");
		}
		Date start = null;
		Date end = null;
		try {
			start = FASTDATEFORMAT_YYYYMMDDHHMMSS.parse(startDate);
			end = FASTDATEFORMAT_YYYYMMDDHHMMSS.parse(endDate);
			if (start.after(end)) {
				throw new Exception("开始日期不能在结束日期之后！");
			}
		} catch (Exception e) {
			throw new Exception("日期格式不对");
		}
		if (start.getMonth() != end.getMonth()) {
			throw new Exception("不能跨月查询！");
		}
		if (StringUtils.isNotBlank(param.getIfName())) {
			param.setIfName("%" + param.getIfName() + "%");
		}
		// 获取数据
		return serviceLogSearchService.findServiceLogInfos(param, pageable,
				userSessionService.getCurrentAuthenticatedUser().getId());
	}

	/**
	 * 导出服务日志
	 * 
	 * @param ifName
	 *            ：接口名称
	 * @param reqResult
	 *            ：请求结果
	 * @param startDateTime
	 *            ：开始时间
	 * @param endDateTime
	 *            ：结束时间
	 * @param request
	 *            ：HTTP 请求对象
	 * @param response
	 *            ：HTTP 响应对象
	 * @throws IOException
	 * @throws InvalidFormatException
	 * @throws SAXException
	 * @throws ParseException
	 */
	@ResponseBody
	@RequestMapping(value = "/serviceLogExport", produces = "application/json")
	public void serviceLogExport(String ifName, String reqResult,
			String startDateTime, String endDateTime,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException, InvalidFormatException, SAXException,
			ParseException {

		// 组装查询对象 START=============================
		ServiceLogSearchParam param = new ServiceLogSearchParam();
		param.setIfName(ifName);
		param.setReqResult(reqResult);
		param.setStartDateTime(startDateTime);
		param.setEndDateTime(endDateTime);
		if (StringUtils.isNotBlank(param.getIfName())) {
			param.setIfName("%" + param.getIfName() + "%");
		}
		// 组装查询对象 END=============================
		Pageable pageable = new PageRequest(
				Constants.DEFAULT_EXPORT_PAGE_COUNT,
				Constants.DEFAULT_EXPORT_DATA_COUNT, null);
		// 获取数据
		Page<AccessLogVo> page = serviceLogSearchService.findServiceLogInfos(
				param, pageable, userSessionService
						.getCurrentAuthenticatedUser().getId());
		List<AccessLogVo> serviceLogs = page.getContent();
		// 转换请求结果
		for (AccessLogVo vo : serviceLogs) {
			vo.setReqResult(RequestResultType.SUCCEED.ValueCode.endsWith(vo
					.getReqResult()) ? "成功" : "失败");
		}
		// 设置导出文件名
		String fileName = new String(
				Constants.HTTP_SERVICE_LOG.getBytes("gb2312"), "ISO8859-1");// 文件名
		// 获取导出模板
		InputStream in = resourceLoader.getResource(
				"classpath:jxls/templatestIn/serviceLogSearch.xls")
				.getInputStream();
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
		response.setHeader("Content-Disposition", "attachment;filename="
				+ fileName + ".xls");
		OutputStream os = response.getOutputStream();
		Context context = new Context();
		context.putVar("serviceLogs", serviceLogs);
		JxlsHelper.getInstance().processTemplate(in, os, context);
	}

	@RequestMapping(value = "/changeForIsSaveLogDesc", produces = "application/json")
	public String changeForIsSaveLogDesc(String interfaceId, String setting) {
		JsonObject jo = new JsonObject();
		if (StringUtils.isBlank(interfaceId) || StringUtils.isBlank(setting)) {
			jo.addProperty(CommonUtils.MSG_FIELD_FAILURES, "失败");
			return jo.toString();
		}
		TraceType type = null;
		if (StringUtils.equals(setting, "1")) {
			type = TraceType.NOTRACE;
		} else {
			type = TraceType.TRACE;
		}
		try {
			boolean result = changeForIsSaveLogDesc(interfaceId, type);
			if (result) {
				jo.addProperty(CommonUtils.MSG_FIELD_SUCCESS, "成功");
			} else {
				jo.addProperty(CommonUtils.MSG_FIELD_FAILURES, "失败");
			}

		} catch (Exception e) {
			jo.addProperty(CommonUtils.MSG_FIELD_FAILURES, e.getMessage());
		}
		return jo.toString();
	}

	@Transactional
	private boolean changeForIsSaveLogDesc(String interfaceId, TraceType type) {
		if (interfaceId != null && type != null) {
			Http http = httpRepository.findOne(interfaceId);
			http.setIsTrace(type.ValueCode);
			httpRepository.save(Arrays.asList(http));
			updateHttpRedisData(http);
			return true;
		}
		return false;
	}

	private boolean updateHttpRedisData(Http http)
			throws ServiceHandlerException {
		try {
			HttpVo target = HttpVo.getInstance(http);
			httpJedisProxy.hset(httpJedisProxy.generateKeyFromObject(target),
					target);
		} catch (JsonProcessingException e) {
			throw new ServiceHandlerException(
					CommonUtils.MSG_JSON_PARSING_ERROR,
					CommonUtils.CODE_JSON_PARSING_ERROR);
		} catch (JedisException e) {
			throw new ServiceHandlerException(
					CommonUtils.MSG_CONNECT_REDIS_FAIED,
					CommonUtils.CODE_CONNECT_REDIS_FAIED);
		} catch (Exception e) {
			throw new ServiceHandlerException(
					CommonUtils.MSG_UPDATE_REDIS_DATA_FAIED,
					CommonUtils.CODE_UPDATE_REDIS_DATA_FAIED);
		}
		return true;
	}
}
